#include "dbms.h"
#include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Transaction.h>
#include <utils/logger.h>
#include <utils/macro.h>

#if 0
namespace dbms {
template <class T>
Dbms<T>::Dbms(const std::string &dbFile, const std::string &tableName)
	: dbFile_(dbFile)
	, tableName_(tableName)
{
}

template <class T> bool Dbms<T>::Insert(const std::string &id, const T &t)
{
	SQLite::Database db(dbFile_, SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
	// Begin transaction
	SQLite::Transaction transaction(db);

	// Prepare query
	std::string sql = "INSERT INTO " + tableName_ + "(" +
					  SqlFromSchema("INSERT") + ")" + " VALUES (?,?)";
	SQLite::Statement insert{db, sql};
	insert.bind(1, id);
	insert.bind(2, Serialize(t));
	insert.exec();
	// Commit transaction
	transaction.commit();
	return true;
}

template <class T> bool Dbms<T>::Update(const std::string &id, const T &t)
{
	SQLite::Database db(dbFile_, SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
	// Begin transaction
	SQLite::Transaction transaction(db);

	// Prepare query
	std::string sql = "UPDATE " + tableName_ + " SET " +
					  SqlFromSchema("UPDATE") + "=? WHERE id=?";
	SQLite::Statement insert{db, sql};
	insert.bind(1, id);
	insert.bind(2, Serialize(t));
	insert.exec();
	// Commit transaction
	transaction.commit();
	return true;
}

template <class T> void Dbms<T>::GetAll(std::function<void(const T &)> getFunc)
{
	SQLite::Database db(dbFile_);

	// Compile a SQL query, containing one parameter (index 1)
	std::string sql = "SELECT * FROM " + tableName_;
	SQLite::Statement query(db, sql);

	// Loop to execute the query step by step, to get rows of result
	while (query.executeStep()) {
		// Demonstrate how to get some typed column value
		const std::string id = query.getColumn(0);
		SQLite::Column data = query.getColumn(1);
		if (data.isNull()) {
			HTELINK_LOG_WARN("some db data error, table = %s, id = %s",
				tableName_.c_str(), id.c_str());
			continue;
		}
		std::string v = data.getString();
		T t = Deserialize(data);
		if (getFunc) {
			getFunc(t);
		}
	}
}

template <class T>
std::string Dbms<T>::FindEqual(
	const T &t, std::function<bool(const T &, const T &)> compareTo)
{
	SQLite::Database db(dbFile_, SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);

	// Compile a SQL query, containing one parameter (index 1)
	std::string sql = "SELECT * FROM " + tableName_;
	SQLite::Statement query(db, sql);

	// Loop to execute the query step by step, to get rows of result
	while (query.executeStep()) {
		// Demonstrate how to get some typed column value
		const std::string id = query.getColumn(0);
		SQLite::Column data = query.getColumn(1);
		if (data.isNull()) {
			continue;
		}
		T to = Deserialize(data.getString());
		if ((compareTo != nullptr)) {
			if (compareTo(t, to)) {
				return id;
			}
		}
	}
	return "";
}

template <class T> std::string Dbms<T>::SqlFromSchema(const std::string &schema)
{
	if (schema == "CTEATE") {
		return std::string("id TEXT PRIMARY KEY,data TEXT");
	} else if (schema == "INSERT") {
		return std::string("id,data");
	} else if (schema == "UPDATE") {
		return std::string("data");
	}
	return std::string();
}

template <class T> void Dbms<T>::CreateTable(const std::string &table)
{
	SQLite::Database db(dbFile_, SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
	SQLite::Transaction transaction(db);

	std::string sql = "CREATE TABLE IF NOT EXISTS" + table + "(" +
					  SqlFromSchema("CREATE") + ");";
	db.exec(sql);

	transaction.commit();
}
} // namespace dbms
#endif